package com.mlh.service.impl;

import com.mlh.entity.LoginUser;
import com.mlh.entity.User;
import com.mlh.service.LoginService;
import com.mlh.utils.JwtUtil;
import com.mlh.utils.RedisCache;
import com.mlh.utils.ResponseResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Objects;

/**
 * @author 缪林辉
 * @date 2024/3/13 21:43
 * @DESCRIPTION
 */
@Service
public class LoginServiceImpl implements LoginService {
    //调用该对象的authenticate方法对密码进行校验
    @Autowired
    private AuthenticationManager authenticationManager;
    @Autowired
    private RedisCache redisCache;
    @Override
    public ResponseResult login(User user) {
        //传入user 包括了用户名和密码 要调用AuthenticationManager的authenticate方法来进行用户认证
        //1.通过SecurityConfig配置类向容器中注入AuthenticationManager 方便这里的调用
        //2.AuthenticationManager的authenticate方法接受的参数是 Authentication 类型
        //因此需要将定义了一个实现 Authentication 接口的对象
        UsernamePasswordAuthenticationToken authenticationToken=
                new UsernamePasswordAuthenticationToken(user.getUserName(),user.getPassword());
        //调用方法后，返回了个Authentication对象
        Authentication authenticate = authenticationManager.authenticate(authenticationToken);
        //根据authenticate是否为null来判断认证是否成功
        if(Objects.isNull(authenticate)){//认证不成功 抛出错误信息
            throw new RuntimeException("用户名或密码错误");
        }
        //认证成功 根据用户id创建jwt对象，并以token的方式返回给浏览器 将返回的用户信息存入到redis中
        //1.需要从返回的 authenticate 来获取到用户id
        //authenticat的Principal属性存储了认证返回的用户信息 即LoginUser
        LoginUser loginUser = (LoginUser)authenticate.getPrincipal();
        String userId = loginUser.getUser().getId().toString();
        //2.返回过来的用户信息存入到redis中
        redisCache.setCacheObject("login:"+userId,loginUser);
        //3.使用userid生成token
        String jwt = JwtUtil.createJWT(userId);
        HashMap<String,String> map = new HashMap<>();
        map.put("token",jwt);
        return new ResponseResult(200,"登陆成功",map);
    }

    //实现退出登录的方法
    @Override
    public ResponseResult logout() {
        UsernamePasswordAuthenticationToken authentication =
                (UsernamePasswordAuthenticationToken)SecurityContextHolder.getContext().getAuthentication();
        //不需要考虑loginUser是否存在，请求能够访问到这个controller说明已经通过认证了
        //那么SecurityContextHolder中必然有authentication
        LoginUser loginUser = (LoginUser)authentication.getPrincipal();
        String  userid = loginUser.getUser().getId().toString();
        redisCache.deleteObject("login:"+userid);
        return new ResponseResult(200,"退出成功");
    }
}
